<?php
/**
 * Library Of Shared Code (LOSC)
 *
 * LICENSE
 *
 * This source file is subject to the New BSD License that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @category   LOSC Framework
 * @package    Controller
 * @subpackage Plugin
 * @copyright  Copyright (c) 2008 Robin Skoglund (http://robinsk.net/)
 * @license    http://creativecommons.org/licenses/BSD/  New BSD License
 */

/**
 * Plugin for handling authentication and authorization
 * 
 * @uses Zend_Acl
 * @uses Zend_Auth
 * @uses Zend_Controller_Action_HelperBroker
 * @uses Zend_Controller_Action_Redirector
 * @uses Zym_Controller_Action_FlashRedirector
 *
 * @category   LOSC Framework
 * @package    Controller
 * @subpackage Plugin
 * @copyright  Copyright (c) 2008 Robin Skoglund (http://robinsk.net/)
 * @license    http://creativecommons.org/licenses/BSD/  New BSD License
 */
class Losc_Controller_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
    /**
     * Whether login is required to dispatch anything at all
     *
     * @var bool
     */
    protected $_requireLogin = false;
    
    /**
     * Mjau
     *
     */
    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
        // get option(s) from db
        $this->_requireLogin =
            Losc_App_Options::getOption('requireLogin', 'auth');
    }
    
    /**
     * Redirects to login page when user is not authenticated
     *
     * @param  Zend_Controller_Request_Abstract $request  request
     * @return void
     */
    protected function _requireLogin(Zend_Controller_Request_Abstract $request)
    {
        if ($request->getModuleName() == 'user' &&
            $request->getControllerName() == 'login') {
            return;
        }
        
        $redir = 'Redirector';
        $redir = Zend_Controller_Action_HelperBroker::getStaticHelper($redir);
        $redir->gotoRouteAndExit(array(), 'login');
    }
    
    /**
     * Forwards to "No access" page when user is not authorized
     *
     * @param  Zend_Controller_Request_Abstract $request  request
     * @return void
     */
    protected function _forbidden(Zend_Controller_Request_Abstract $request)
    {
        // forward instead of redirect
        $request->setActionName('forbidden')
                ->setControllerName('error')
                ->setModuleName('default')
                ->setDispatched(true);
    }
    
    /**
     * Forwards to "No access" page when user is not authorized
     *
     * @param  Zend_Controller_Request_Abstract $request  request
     * @return void
     */
    protected function _unauthorized(Zend_Controller_Request_Abstract $request)
    {
        // forward instead of redirect
        $request->setActionName('unauthorized')
                ->setControllerName('error')
                ->setModuleName('default')
                ->setDispatched(true);
    }

    /**
     * Authenticate user and check authorization before dispatching request
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @return void
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $auth = Zend_Auth::getInstance();
        
        if ($this->_requireLogin && !$auth->hasIdentity()) {
            $this->_requireLogin($request);
        }
        
        $acl = Losc_Security_Acl_Doctrine::getInstance();
        
        // determine if current user is allowed for the given request
        if (!$acl->isAllowedRequest($request)) {
            // not allowed
            if (!$auth->hasIdentity()) {
                // not logged in
                $this->_unauthorized($request);
            } else {
                // logged in, but no access
                $this->_forbidden($request);
            }
        }
    }
}
